/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package GestionTuplas;
import GestionTuplas.IdentificadorPagina;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import GestionTuplas.Clases.*;
/**
 *
 * @author fredy
 */
public class Pagina implements Iterable<Tupla> {
    /** Las tuplas de la página. */
    private List<Tupla> tuplas;
    /** El ID de la página. */
    private IdentificadorPagina idPagina;
    /** El esquema de la relación al que pertenece la página. */
    private Relacion relacion;
    /** El espacio libre en la página. */
    private int espacioLibre;

    public Pagina(Relacion relacion, IdentificadorPagina idPagina) {
        this.relacion = relacion;
        this.idPagina = idPagina;
        this.tuplas = new ArrayList<Tupla>();
        // tamaño de página 4k
        espacioLibre = 4096 - Convert.INT_SIZE;
    }

    public Relacion getRelacion() {
        return relacion;
    }

    public boolean hayEspacio(Tupla t) {
        return espacioLibre >= GestorIOTupla.byteSize(getRelacion(), t);
    }

    public int getNumeroDeTuplas() {
        return tuplas.size();
    }

    public void adicionarTupla(Tupla tupla)
            throws ArrayIndexOutOfBoundsException {

        if (hayEspacio(tupla)) {
            tuplas.add(tupla);
            espacioLibre -= GestorIOTupla.byteSize(getRelacion(), tupla);
        } else {
            throw new ArrayIndexOutOfBoundsException("no hay espacio en la página.");
        }
    }

    public void setTupla(int index, Tupla tupla)
            throws ArrayIndexOutOfBoundsException {

        if (!puedeCambiar(index, tupla)) {
            throw new ArrayIndexOutOfBoundsException("no hay espacio en la página.");
        }
        tuplas.set(index, tupla);
    }

    public boolean puedeCambiar(int index, Tupla nt) {

        return (espacioLibre
                + GestorIOTupla.byteSize(getRelacion(), tuplas.get(index))
                - GestorIOTupla.byteSize(getRelacion(), nt)) >= 0;
    }

    public void intercambiar(int x, int y) {
        Tupla t = tuplas.get(x);
        tuplas.set(x, tuplas.get(y));
        tuplas.set(y, t);
    }

    public Tupla recuperarTupla(int index) {

        return tuplas.get(index);
    }

    public IdentificadorPagina getIdentificadorPagina() {
        return idPagina;
    }

    @Override
    public Iterator<Tupla> iterator() {
        return new IteradorDePagina();
    }

    private class IteradorDePagina implements Iterator<Tupla> {

        /** El actual indice del iterator. */
        private int indiceActual;

        public IteradorDePagina() {
            indiceActual = 0;
        }

        @Override
        public boolean hasNext() {
            return indiceActual < tuplas.size();
        }

        @Override
        public Tupla next() {
            return tuplas.get(indiceActual++);
        }

        @Override
        public void remove() {
            int size = GestorIOTupla.byteSize(getRelacion(),
                    tuplas.get(indiceActual));
            espacioLibre += size;
            tuplas.remove(indiceActual);
        }
    }

    @Override
    public String toString() {

        StringBuilder sb = new StringBuilder();
        sb.append("pagina: ").append(getIdentificadorPagina()).append(", tuplas: {\n");
        int tid = 0;
        for (Tupla it : this) {
            sb.append("\t").append(tid++).append(": ").append(it.toString()).append("\n");
        }
        sb.append("}");
        return sb.toString();
    }
}
